package com.swang.security.sdk;

import java.text.MessageFormat;
import java.util.Set;

import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.session.SessionInformation;

import com.alibaba.fastjson.JSON;
import com.swang.security.sdk.integration.RedisClient;

/**
 * @ClassName: SwangSecurityRedisHandler
 * @Description: spring security的session的redis操作
 * @author swang
 * @date 2017年4月15日 下午2:09:13
 */
public class SwangSecurityRedisHandler implements SecurityRedisHandler {
	private final Log logger = LogFactory.getLog(getClass());
	
	private RedisClient redisClient;

	public void setRedisClient(RedisClient redisClient) {
		this.redisClient = redisClient;
	}

	@Override
	public Set<String> getAllPrincipals() {
		return redisClient.smembers(SWANG_SECURITY_SESSIONMANAGE_PRINCIPAL_KEY);
	}
	
	@Override
	public Set<String> getAllSessionIds(Object principal) {
		return redisClient.smembers(MessageFormat.format(SWANG_SECURITY_SESSIONMANAGE_PRINCIPAL_SESSIONID, createPrincipalKey(principal)));
	}

	@Override
	public SessionInformation getSessionInformation(String sessionId) {
		String redisSessionInfo= redisClient.get(MessageFormat.format(SWANG_SECURITY_SESSIONMANAGE_SESSIONID_SESSIONINFO, sessionId));
        if(StringUtils.isEmpty(redisSessionInfo)){
        	return null;
        }
        byte[] objectByte = JSON.parseObject(redisSessionInfo,byte[].class);
        SessionInformation sessionInfo = SerializationUtils.deserialize(objectByte);
        if(logger.isDebugEnabled()){
        	logger.debug("在redis中获取session详细信息，入参sessionId："+sessionId+"，sessionInfo："+JSON.toJSONString(sessionInfo));
        }
        return sessionInfo;
	}

	@Override
	public void savePrincipalSessionId(Object principal, String sessionId) {
		final String principalSessionId = MessageFormat.format(SWANG_SECURITY_SESSIONMANAGE_PRINCIPAL_SESSIONID, createPrincipalKey(principal));
		redisClient.sadd(principalSessionId, sessionId);
	}

	@Override
	public void savePrincipalKey(Object principal) {
		redisClient.sadd(SWANG_SECURITY_SESSIONMANAGE_PRINCIPAL_KEY, createPrincipalKey(principal));
	}
	
	@Override
	public void saveSessionInfoBySessoinId(String sessionId, SessionInformation sessionInfo) {
		String byteStr = JSON.toJSONString(SerializationUtils.serialize(sessionInfo));
		redisClient.set(MessageFormat.format(SWANG_SECURITY_SESSIONMANAGE_SESSIONID_SESSIONINFO, sessionId), byteStr);
	}

	@Override
	public void removeSessionInfo(String sessionId) {
		if(logger.isDebugEnabled()){
        	logger.debug("删除session的详细信息 sessionId:" + sessionId);
		}
        //删除session的详细信息
		redisClient.expire(MessageFormat.format(SWANG_SECURITY_SESSIONMANAGE_SESSIONID_SESSIONINFO, sessionId), REDISDELTIME);
	}

	@Override
	public Long removePrincipalSessionId(Object principal, String sessionId) {
		if(logger.isDebugEnabled()){
        	logger.debug("删除用户信息与sessionId的对应信息 PrincipalKey:" + createPrincipalKey(principal));
        }
		return redisClient.srem(MessageFormat.format(SWANG_SECURITY_SESSIONMANAGE_PRINCIPAL_SESSIONID, createPrincipalKey(principal)), sessionId);
	}

	@Override
	public void removePrincipalKey(Object principal) {
		if(logger.isDebugEnabled()){
        	logger.debug("删除PrincipalKey对应信息 PrincipalKey:{0}" + createPrincipalKey(principal));
        }
		redisClient.srem(SWANG_SECURITY_SESSIONMANAGE_PRINCIPAL_KEY, createPrincipalKey(principal));
	}

	@Override
	public Long countPrincipalSessionId(Object principal) {
		return redisClient.scard(MessageFormat.format(SWANG_SECURITY_SESSIONMANAGE_PRINCIPAL_SESSIONID, createPrincipalKey(principal)));
	}
	
	/**
     * 获取表示一个appAuthName唯一用户的sesion的key
     * @author swang
     * @date 2017年4月15日 上午11:32:08
     * @param principal
     * @return
     */
    private String createPrincipalKey(Object principal){
    	if (principal instanceof SwangUserDetails) {
    		SwangUserDetails user = (SwangUserDetails) principal;
    		StringBuilder principalKey = new StringBuilder();
    		String appAuthName = StringUtils.isBlank(user.getAppAuthName())?"":user.getAppAuthName();
            principalKey.append(appAuthName).append(ADDCLIENTSPLIT).append(user.getUserId());
            return principalKey.toString();
		}
    	return null;
    }

}
